package at.donalfonso.ui.group;

import java.io.Serializable;
import java.util.Random;

import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageProducer;
import javax.jms.ObjectMessage;
import javax.jms.Session;
import javax.jms.Topic;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import at.donalfonso.model.Gruppe;
import at.donalfonso.model.GruppeStatus;
import at.donalfonso.utility.JMSUtility;

public class GruppeThreadJMS extends Thread {

	protected JMSUtility jmsSync;
	
	private Gruppe gruppe;
	private Random random;
	
	private int filiale;
	
	private Logger logger = LoggerFactory.getLogger(this.getClass());

	
	public GruppeThreadJMS(Gruppe gruppe) {
		this.gruppe = gruppe;
		this.filiale = gruppe.getFilialID();
		random = new Random();
	}
	
	@Override
	public void run() {
		try {
			jmsSync = new JMSUtility(filiale);
			jmsSync.getConnection().start();
			
			MessageProducer prodEingang = jmsSync.getSession().createProducer(jmsSync.getQueueEingang());
			
			// Gruppe stellt sich am Eingang an
			ObjectMessage om = jmsSync.getSession().createObjectMessage(gruppe);
			prodEingang.send(om);
			logger.debug("Gruppe gesendet");
			
			updateGui(gruppe);
			
			String sel1 = "ID = '" + gruppe.getId() + "' AND GruppeStatus = '";
			String sel2 =  GruppeStatus.WARTEN + "'";
			MessageConsumer consSaal = jmsSync.getSession().createConsumer(jmsSync.getQueueSaal(), sel1 + sel2);
			
			// Gruppe wartet auf Tischzuweisung
			Message msg = consSaal.receive();
			logger.debug("GruppeThreadJMS " + gruppe.getId() + ": Message received for Selector: " + sel1 + sel2);
			logger.debug("Message: " + msg);
			// platznehmen und bestellen
			handleMessage(msg);
			
			sel2 = GruppeStatus.ESSEN + "'";
			consSaal = jmsSync.getSession().createConsumer(jmsSync.getQueueSaal(), sel1 + sel2);
			// Gruppe wartet auf Essen
			msg = consSaal.receive();
			logger.debug("GruppeThreadJMS " + gruppe.getId() + ": Message received for Selector: " + sel1 + sel2);
			logger.debug("Message: " + msg);
			// essen und Zahlungswunsch
			handleMessage(msg);
			
			sel2 = GruppeStatus.GEGANGEN + "'";
			Session sess = jmsSync.getConnection().createSession(false, Session.AUTO_ACKNOWLEDGE);
			consSaal = sess.createConsumer(jmsSync.getQueueSaal(), sel1 + sel2);
			// Gruppe geht und gibt Tisch frei
			logger.debug("vor warten auf Gruppe gegangen, Selector: " + sel1 + sel2);
			msg = consSaal.receive();
			logger.debug("GruppeThreadJMS " + gruppe.getId() + ": Message received for Selector: " + sel1 + sel2);
			logger.debug("Message: " + msg);
/*
			sel1 = "Class = '" + Tisch.class.getSimpleName() + 
					"' AND ID = '" + gruppe.getTischId() + "'";
			consSaal = jmsSync.getSession().createConsumer(jmsSync.getQueueSaal(), sel1);
			// Tisch der Gruppe auslesen
			msg = consSaal.receive();
			
			if (msg instanceof ObjectMessage) {
				Serializable s =((ObjectMessage) msg).getObject();
				if (s instanceof Tisch) {
					Tisch t = (Tisch) s;
					logger.debug("Tisch " + t.getId() + " empfangen.");
					t.setGruppeId("");
					t.setStatus(TischStatus.FREI);
					ObjectMessage omt = jmsSync.getSession().createObjectMessage(t);
					omt.setStringProperty("Class", t.getClass().getSimpleName());
					omt.setStringProperty("ID", t.getId());
					omt.setStringProperty("TischStatus", t.getStatus().toString());
					prodSaal.send(omt);
					
					updateGui(t);
				}
			}
*/			
		} catch (JMSException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	/**
	 * Über das Topic "Gui_update" werden Statusänderungen kommuniziert.
	 */
	public void updateGui(Serializable object){
		
		logger.debug("Updating Gui.");
		
		try {
			Topic topic = jmsSync.getTopicGuiUpdate();
			Message msg = jmsSync.getSession().createObjectMessage(object);
			msg.setStringProperty("Class", object.getClass().getSimpleName());
			
			MessageProducer producer = jmsSync.getSession().createProducer(topic);
			
			producer.send(msg);
			
			producer.close();
			
		} catch (JMSException e) {
			
			logger.debug("GUI Update failed.");
			
			e.printStackTrace();
		}	
	}
	
	public void handleMessage(Message message) {
		logger.debug("in handleMessage(), my Gruppe.getId(): " + gruppe.getId());
		try {
		
			if (message instanceof ObjectMessage) {
				Serializable s = ((ObjectMessage) message).getObject();
				if (s instanceof Gruppe) {
					Gruppe g = (Gruppe) s;
					logger.debug("Gruppe empfangen: " + g);
					if (g.getId().equals(gruppe.getId()) && g.getStatus() == GruppeStatus.WARTEN) {
						logger.debug("gt platznehmen");
						gruppe = g;
						platznehmen();
					}
					if (g.getId().equals(gruppe.getId()) && g.getStatus() == GruppeStatus.ESSEN) {
						logger.debug("gt essen");
						gruppe = g;
						essen();
					}
				}
			}
		} catch (JMSException | InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}
	
	private void platznehmen()  throws JMSException {
		gruppe.setStatus(GruppeStatus.SITZEN);
		
		ObjectMessage om = jmsSync.getSession().createObjectMessage(gruppe);
		om.setStringProperty("Class", gruppe.getClass().getSimpleName());
		om.setStringProperty("ID", gruppe.getId());
		om.setStringProperty("GruppeStatus", gruppe.getStatus().toString());
		MessageProducer prod = jmsSync.getSession().createProducer(jmsSync.getQueueSaal());
		prod.send(om);
		
		updateGui(gruppe);
		
		logger.debug("platznehmen(): Gruppe gesendet: " + gruppe);
	}
	
	private void essen() throws InterruptedException, JMSException {
		logger.debug("Gruppe " + gruppe.getId() + ": Essen");
		Thread.sleep((random.nextInt(3) + 3) * 1000);
		logger.debug("Gruppe " + gruppe.getId() + " hat fertig gegessen.");
		gruppe.setStatus(GruppeStatus.BEZAHLEN);
		
		ObjectMessage om = jmsSync.getSession().createObjectMessage(gruppe);
		om.setStringProperty("Class", gruppe.getClass().getSimpleName());
		om.setStringProperty("ID", gruppe.getId());
		om.setStringProperty("GruppeStatus", gruppe.getStatus().toString());
		MessageProducer prod = jmsSync.getSession().createProducer(jmsSync.getQueueSaal());
		prod.send(om);
		
		updateGui(gruppe);
	}

/*	
	public JMSUtility getJMSUtility(){
		if (jmsUtility == null){
			jmsUtility = new JMSUtility();
		}
		return jmsUtility;
	}
*/
}
